<?php
/**
 * generic HTTP request class via cUrl
 *
 * @category com.commentor.httpRequest
 * @author   bruce.li <bruce.li@commentor.com>
 */
class Util_HttpRequest
{
    /**
     * request url
     *
     * @var str
     */
    private $_url = null;


    /**
     * request type post|get
     *
     * @var str
     */
    private $_requestType = 'POST';


    /**
     * query data - array for post/get, string for xml
     *
     * @var mixed
     */
    private $_queryData = array();


    /**
     * query string separator
     *
     * @var char
     */
    private $_querySeparator = '&';


    /**
     * response text
     * will be string if post/get, or str if xml...
     *
     * @var mixed
     */
    private $_response = null;


    /**
     * status
     *
     * @var int
     */
    private $_status = 0;


    /**
     * timeout
     *
     * @var int
     */
    private $_timeOut = 30;


    /**
     * extra config
     *
     * @var array
     */
    private $_config = array();


    /**
     * constructor
     *
     * @param str   $url         the url
     * @param str   $requestType type of request
     * @param int   $timeOut     the timeout, in seconds
     * @param array $config      extra config items
     *
     * @throw Exception
     * @access public
     * @return void
     */
    public function __construct($url = null, $requestType = 'POST', $timeOut = 30)
    {
        if (!is_null($url)) {
            $this->setUrl($url);
        }
        $this->setTimeOut($timeOut);
        $this->setRequestType($requestType);

    }// end __construct

/*--------------------------------[getters and setters]--------------------------------*/

    /**
     * set url
     *
     * @param $url
     *
     * @throw Exception
     * @return void
     */
    public function setUrl($url)
    {
        if (empty($url)) {
            throw new Exception('URL is empty');
        }

        // set the url
        $this->_url = str_replace(' ', '%20', $url);

        return $this;
    }// end setUrl


    /**
     * set timeout
     *
     * @param $timeOut
     *
     * @throw Exception
     * @return void
     */
    public function setTimeOut($timeOut)
    {
        if (empty($timeOut)) {
            throw new Exception('timeout is invalid');
        }

        // set the timeout
        $this->_timeOut = (int) $timeOut;

    }// end setTimeOut


    /**
     * set request type
     * @param $type
     *
     * @throw Exception
     * @return void
     */
    public function setRequestType($type)
    {
        $type = strtoupper($type);

        if (empty($type)) {
            throw new Exception('Request type is empty');
        } else {
            if (!in_array($type, array('POST', 'GET'))) {
                throw new Exception('Request type is invalid');
            }
        }

        $this->_requestType = $type;

    }// end setRequestType


    /**
     * set the query data
     *
     * @param array $data the query data
     *
     * @throw Exception
     * @return cb_utility_http_request
     */
    public function setQueryData($data)
    {
        $this->_queryData = $data;
        return $this;

    }// end setQueryData


    /**
     * get request status
     *
     * @return int
     */
    public function getStatus()
    {
        return $this->_status;

    }// end getStatus


    /**
     * get response data
     *
     * @return mixed
     */
    public function getResponse()
    {
        return $this->_response;

    }// end getResponse

/*--------------------------------[exec]--------------------------------*/

    /**
     * send and retrieve response
     *
     * @throw Exception
     * @return mixed
     */
    public function send()
    {
        // validate
        if (empty($this->_url)) {
            throw new Exception('URL is invalid');
        }

        // the function to send the request and get the response
        $ch = curl_init($this->_url);
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeOut);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,  false);

        // set the data for post/get with data array
        if (is_array($this->_queryData)) {
            // compose querystring
            $queryStrings = array();
            foreach ($this->_queryData as $k => $v) {
                $queryStrings[] = $k . '=' . $v;
            }

            // type change
            $queryStrings = join($this->_querySeparator, $queryStrings);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $queryStrings);

            if ($this->_requestType === 'POST') {
                curl_setopt_array($ch, array(
                    CURLOPT_POST => true,
                    CURLOPT_HTTPGET => false));
            } else {
                curl_setopt_array($ch, array(
                    CURLOPT_POST => false,
                    CURLOPT_HTTPGET => true));
                // check if there's already query strings
                if (strpos($this->_url, '?') !== false) {
                    $this->_url .= '&' . $queryStrings;
                } elseif (strlen($queryStrings) > 0) {
                    $this->_url .= '?' . $queryStrings;
                }
            }
        } else { // xml POST
            curl_setopt_array($ch, array(
                CURLOPT_POSTFIELDS => $this->_queryData,
                CURLOPT_POST => true));
        }

        // then send it and get the response and status back...
        $response = curl_exec($ch);

        if (curl_errno($ch)) {
            throw new Exception('HTTP REQUEST ERROR:' . curl_error($ch), curl_errno($ch));
        }

        // get info out... for status... if 200 it's good, otherwise die
        $this->_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        // close it
        curl_close($ch);
        // do the response...
        return $this->_response = $response;

    }// end send
}
?>
